<?php

namespace app\common\controller;

use think\cache\driver\Redis;
use think\Controller;
use think\Db;

use TencentCloud\Common\CommonClient;
use TencentCloud\Common\Exception\TencentCloudSDKException;
use TencentCloud\Common\Credential;
use TencentCloud\Common\Profile\ClientProfile;
use TencentCloud\Common\Profile\HttpProfile;

/**
 * 公共资源-短信发送 验证
 */
class Sms extends Controller
{
    /**
     * 发送短信
     * @param  $phone
     * @param  $code
     * @param  $type
     * @param  $sign
     * @return array|mixed | 0 成功 !=0失败
     * @since 2023/08/04
     * @author ZhangXuanNeng
     */
    public function sendSms($phone, $code, $type, $sign)
    {
        $smsType = Db::name('default_config')->where('name', 'sms_type')->value('value');
        $smsType = json_decode($smsType, true);
        $class = $smsType['value'] ?? 'SmsChuangLan';
        $class = $class ? $class : 'SmsChuangLan';
        write_log('INFO', 'Sms.php', '短信发送平台:' . $class, 'sms', true);
        $className = "app\\common\\controller\\{$class}";
        $smsSend = new $className;
        $text = $this->getSmsText($type);
        if (!$text) {
            return ['code' => -1, 'return_code' => 'fail', 'msg' => '未知类型'];
        }
        return $smsSend->sendSms($phone, $code, $type, $sign, $text);
    }

    /**
     * 获取模板
     * @param int $type 1=手机注册；2=手机验证登录；3=手机验证登录密码发送 4=更换手机号  5=注销账号 6=绑定手机 7=忘记密码 8=后台登录
     * @author ZhangXuanNeng
     */
    public function getSmsText(int $type)
    {
        switch ($type) {
            case 1:
                $text = '，您正在使用手机注册账户服务[验证码告知他人将导致帐号泄露，请勿泄露]';
                break;
            case 2:
                $text = '，您正在使用手机登录账号服务，验证码请勿告知他人，如非本人操作，请忽略本短信';
                break;
            case 3:
                $text = '，您的手机已成功注册，密码为';
                break;
            case 4:
                $text = '，您正在使用手机更换绑定[验证码告知他人将导致帐号泄露，请勿泄露]';
                break;
            case 5://注销账号
                $text = '，您正在使用注销账号[验证码告知他人将导致帐号泄露，请勿泄露]';
                break;
            case 6://绑定手机
                $text = '，您正在使用手机账号绑定服务，验证码请勿告知他人，如非本人操作，请忽略本短信';
                break;
            case 7://忘记密码
                $text = '，您正在使用手机账号找回密码服务，验证码请勿告知他人，如非本人操作，请忽略本短信';
                break;
            case 8://后台登录
                $text = '，您正在使用手机号登录，验证码请勿告知他人，如非本人操作，请忽略本短信';
                break;
            default:
                $text = false;
        }

        return $text;
    }

    /**
     * 验证码验证
     * @param $phone
     * @param $code
     * @return array |0 成功 !0失败
     * @since 2023/08/04
     * @author ZhangXuanNeng
     */
    public function smsVerify($phone, $code): array
    {
        $redis = new Redis(getRedisConfig());
        $res = $redis->get($phone);
        if (empty($res)) {
            return ['code' => -1, 'return_code' => 'fail', 'msg' => '验证码已过期！请重新获取'];
        }
        if ($res != $code) {
            $num = $redis->get($phone . '_num');
            $redis->set($phone . '_num', $num + 1, 60);
            if ($redis->get($phone . '_num') >= 3) {
                $redis->rm($phone . '_num');
                $redis->rm($phone);
            }
            return ['code' => -1, 'return_code' => 'fail', 'msg' => '输入验证码不正确'];
        }
        $redis->rm($phone . '_num');
        $redis->rm($phone);
        return ['code' => 0, 'return_code' => 'success', 'msg' => '验证通过'];
    }

    /**
     * Notes: 腾讯云发送短信
     * User: liubaoqiang
     * DateTime: 2025/1/3 10:25
     * @param $phone
     * @param $code
     * @param int $type
     * @return array
     */
    public function tencentSms($phone, $code, int $type = 1): array
    {
        try {
            // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
            // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，
            // 请参见：https://cloud.tencent.com/document/product/1278/85305
            // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
            $cred = new Credential(config('Sms.TENCENTCLOUD_SECRET_ID'), config('Sms.TENCENTCLOUD_SECRET_KEY'));
            $httpProfile = new HttpProfile();
            $httpProfile->setEndpoint(config('Sms.SMS_URL'));
            $clientProfile = new ClientProfile();
            $clientProfile->setHttpProfile($httpProfile);
            $client = new CommonClient("sms", "2021-01-11", $cred, "ap-nanjing", $clientProfile);
            switch ($type) {
                case 1:
                    $templateId = config('Sms.TEMPLATE_ID.LOGIN_REGISTER');
                    break;
                case 2:
                    $templateId = config('Sms.TEMPLATE_ID.UPDATE_PASSWORD');
                    break;
                case 3:
                    $templateId = config('Sms.TEMPLATE_ID.UPDATE_PHONE');
                    break;
                default:
                    $templateId = config('Sms.TEMPLATE_ID.LOGIN_REGISTER');
            }
            $params = [
                'PhoneNumberSet'   => [$phone],
                'SmsSdkAppId'      => config('Sms.TENCENTCLOUD_SMS_SDK_APPID'),
                'TemplateId'       => $templateId,
                'SignName'         => config('Sms.TENCENTCLOUD_SMS_SIGN_NAME'),
                'TemplateParamSet' => ["$code"]
            ];
            $params = json_encode($params);
            $resp = $client->callJson("SendSms", json_decode($params));
            if (isset($resp) && $resp['SendStatusSet'][0]['Code'] != "Ok") {
                write_log('ERROR', 'Sms.php', '短信发送失败：手机号：' . $phone . '; 错误信息：' . $resp['SendStatusSet'][0]['Code'], 'sms', true);
                return ['code' => -1, 'return_code' => $resp['SendStatusSet'][0]['Code'], 'msg' => '短信发送失败'];
            }
            $redis = new Redis(getRedisConfig());
            $redis->set($phone, $code, 300);
            return ['code' => 0, 'return_code' => $resp['SendStatusSet'][0]['Code'], 'msg' => '短信发送成功'];
        } catch (TencentCloudSDKException $e) {
            write_log('ERROR', 'Sms.php', '短信发送失败：手机号：' . $phone . '; 错误信息：' . $e->getMessage(), 'sms', true);
            return ['code' => -1, 'return_code' => 'fail', 'msg' => '短信发送失败'];
        }
    }
}
